home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 4 / Apprentice-Release4.iso / Source Code / C / Applications / MacPerl 5.0.3 / MacPerl Source ƒ / MacPerl5 / MPEditions.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-10-08  |  38.9 KB  |  1,423 lines  |  [TEXT/MPS ]

  1. /*********************************************************************
  2. Project    :    MacPerl            -    Real Perl Application
  3. File        :    MPEditions.c    -
  4. Author    :    Matthias Neeracher
  5.  
  6. A lot of this code is borrowed from 7Edit written by
  7. Apple Developer Support UK
  8.  
  9. Language    :    MPW C
  10.  
  11. $Log: MPEditions.c,v $
  12. Revision 1.2  1994/05/04  02:50:54  neeri
  13. Fix segment names.
  14.  
  15. Revision 1.1  1994/02/27  23:00:31  neeri
  16. Initial revision
  17.  
  18. Revision 0.3  1993/09/18  00:00:00  neeri
  19. Runtime
  20.  
  21. Revision 0.2  1993/05/30  00:00:00  neeri
  22. Support Console Windows
  23.  
  24. Revision 0.1  1993/05/29  00:00:00  neeri
  25. Compiles correctly
  26.  
  27. *********************************************************************/
  28.  
  29. #include <OSUtils.h>
  30. #include <Resources.h>
  31. #include <Errors.h>
  32. #include <AppleEvents.h>
  33.  
  34. #include "MPEditions.h"
  35.  
  36. /**-----------------------------------------------------------------------
  37.         Name:         GetERefCon
  38.         Purpose:        Return the sectHandle (our own type) stored in
  39.                         the refcon of the SectionRecord.
  40.     -----------------------------------------------------------------------**/
  41.  
  42. #if !defined(powerc) && !defined(__powerc)
  43. #pragma segment Editions
  44. #endif
  45.  
  46. pascal SectHandle GetERefCon(SectionHandle EMSection)
  47. {
  48.     SectHandle aSectHandle;
  49.  
  50.     aSectHandle = (SectHandle)(*EMSection)->refCon;
  51.     return(aSectHandle);
  52. }
  53.  
  54. /**-----------------------------------------------------------------------
  55. Name:         SetERefCon
  56. Purpose:        Store a handle to our own SectRecord in the refcon
  57.                 field of the SectionRecord.
  58. -----------------------------------------------------------------------**/
  59.  
  60. #if !defined(powerc) && !defined(__powerc)
  61. #pragma segment Editions
  62. #endif
  63.  
  64. pascal void SetERefCon(SectionHandle EMSection, SectHandle aSectHandle)
  65. {
  66.     (*EMSection)->refCon = (long)aSectHandle;
  67. }
  68.  
  69. /**-----------------------------------------------------------------------
  70.         Name:         AddSection
  71.         Purpose:        Add our own section record to the document linked
  72.                         list.  Set up the first and last section variables.
  73.     -----------------------------------------------------------------------**/
  74.  
  75. #if !defined(powerc) && !defined(__powerc)
  76. #pragma segment Editions
  77. #endif
  78.  
  79. pascal void AddSection(SectHandle newSection, DPtr aDocument)
  80. {
  81.     if (aDocument->kind != kDocumentWindow)
  82.         return;
  83.         
  84.     /*
  85.         add the section to the document
  86.     */
  87.     aDocument->u.reg.numSections += 1;
  88.  
  89.     /*
  90.         if not NIL, add the new section to the list after the last element
  91.     */
  92.  
  93.     if (aDocument->u.reg.lastSection)
  94.         (*(aDocument->u.reg.lastSection))->fNextSection = newSection;
  95.     else
  96.         aDocument->u.reg.firstSection = newSection;
  97.  
  98.     aDocument->u.reg.lastSection = newSection;
  99.     (*newSection)->fNextSection  = nil;
  100. }
  101.  
  102. /**-----------------------------------------------------------------------
  103.         Name:         CreateSection
  104.         Purpose:        Create a new section record to hold a Publisher or
  105.                         Subscriber. Link this to the SectionRecord.
  106.     -----------------------------------------------------------------------**/
  107.  
  108. #if !defined(powerc) && !defined(__powerc)
  109. #pragma segment Editions
  110. #endif
  111.  
  112. pascal void CreateSection(SectionHandle   EMSection,
  113.                                   short           sectionID,
  114.                                   short           theStart,
  115.                                   short           theEnd,
  116.                                   DPtr            aDocument,
  117.                                   RgnHandle       theBorder)
  118.  
  119. {
  120.     SectHandle    newSection;
  121.  
  122.     if (aDocument->kind != kDocumentWindow)
  123.         return;
  124.         
  125.     /*
  126.         create a section and call AddSection to add it to the list
  127.     */
  128.     newSection = (SectHandle)NewHandle(sizeof(SectRec));
  129.  
  130.     if (newSection) {
  131.         (*newSection)->fSectionID   = sectionID;
  132.         (*newSection)->fNextSection = nil;
  133.         (*newSection)->fSectHandle  = EMSection;
  134.         (*newSection)->fStart       = theStart;
  135.         (*newSection)->fEnd         = theEnd;
  136.         (*newSection)->fCount       = theEnd - theStart;
  137.         (*newSection)->fBorderRgn   = theBorder;
  138.         (*newSection)->fDocument    = aDocument;
  139.  
  140.         /*
  141.             put a reference to our section record in the section's refCon field
  142.         */
  143.  
  144.         SetERefCon(EMSection, newSection);
  145.         AddSection(newSection, aDocument);
  146.     }
  147. }
  148.  
  149.  /**-----------------------------------------------------------------------
  150.         Name:         DeleteASection
  151.         Purpose:        Delete the section from the list.
  152.                         Called when 'Cancel Publisher/Subscriber is chosen in
  153.                         the 'Section Options' dialog.
  154.     -----------------------------------------------------------------------**/
  155.  
  156. #if !defined(powerc) && !defined(__powerc)
  157.     #pragma segment Editions
  158. #endif
  159.  
  160. pascal void DeleteASection(SectHandle sectToDelete, DPtr theDoc)
  161. {
  162.     SectHandle    currSect;
  163.     SectHandle    prevSect;
  164.  
  165.     if (theDoc->kind != kDocumentWindow)
  166.         return;
  167.  
  168.     currSect = theDoc->u.reg.firstSection;
  169.     prevSect = nil;
  170.  
  171.     while (currSect) {
  172.         if (currSect == sectToDelete) {
  173.             /*
  174.                 unlink the section from the list
  175.             */
  176.             if (prevSect)
  177.                 (*prevSect)->fNextSection = (*currSect)->fNextSection;
  178.  
  179.             if (currSect == theDoc->u.reg.firstSection)
  180.                 theDoc->u.reg.firstSection = nil;
  181.  
  182.             if (currSect == theDoc->u.reg.lastSection)
  183.                 theDoc->u.reg.lastSection = nil;
  184.         }
  185.         prevSect = currSect;
  186.         currSect = (*currSect)->fNextSection;
  187.     }
  188. }
  189.  
  190. /**-----------------------------------------------------------------------
  191.         Name:         ReadASection
  192.         Purpose:        Read in a section from disk
  193.                         Read in the rAliasType and rsectionType resources and register
  194.                         the section with the document.
  195.     -----------------------------------------------------------------------**/
  196.  
  197. #if !defined(powerc) && !defined(__powerc)
  198. #pragma segment Editions
  199. #endif
  200.  
  201. pascal void ReadASection(SectHandle aSectHandle)
  202. {
  203.     SectionHandle     aSectionHandle;
  204.     AliasHandle         anAlias;
  205.     OSErr               err;
  206.     FSSpec            myFSSpec;
  207.     Boolean            ignore;
  208.  
  209.     /*read in the rAliasType and rSectionType resources*/
  210.  
  211.     aSectionHandle = (SectionHandle)Get1Resource(rSectionType, (*aSectHandle)->fSectionID);
  212.     err            = HandToHand((Handle *)&aSectionHandle);
  213.     (*aSectHandle)->fSectHandle = aSectionHandle;
  214.     SetERefCon(aSectionHandle, aSectHandle);
  215.  
  216.     anAlias = (AliasHandle)Get1Resource(rAliasType, (*aSectHandle)->fSectionID);
  217.     err     = HandToHand((Handle *)&anAlias);
  218.     (*aSectionHandle)->alias = anAlias;
  219.  
  220.     /*now register the section*/
  221.  
  222.     err = ResolveAlias(nil, (*aSectionHandle)->alias, &myFSSpec, &ignore);
  223.     if (err) {
  224.         ShowError((StringPtr) "\pResolve Alias", err);
  225.         return;
  226.     }
  227.  
  228.     err = RegisterSection(&myFSSpec, aSectionHandle, &ignore);
  229.  
  230.     if ((err) && (err != notThePublisherWrn) && (err != multiplePublisherWrn)) {
  231.         ShowError((StringPtr) "\pRegisterSection", err);
  232.         return;
  233.     }
  234.     SetSelectionRgn(((*aSectHandle)->fDocument)->theText,
  235.                          (*aSectHandle)->fStart,
  236.                                     (*aSectHandle)->fEnd,
  237.                                     &(*aSectHandle)->fBorderRgn);
  238.     InvalRgn((*aSectHandle)->fBorderRgn);
  239. }
  240.  
  241. /**-----------------------------------------------------------------------
  242. Name:         ReadAllSectionResources
  243. Purpose:        Call the above routine to read in the resources for
  244.                 each section in the document.
  245. -----------------------------------------------------------------------**/
  246. #if !defined(powerc) && !defined(__powerc)
  247. #pragma segment Editions
  248. #endif
  249.  
  250. pascal void ReadAllSectionResources(DPtr aDoc)
  251. {
  252.     SectHandle  theSection;
  253.  
  254.     if (aDoc->kind != kDocumentWindow)
  255.         return;
  256.         
  257.     /*read in each section resource*/
  258.  
  259.     theSection = aDoc->u.reg.firstSection;
  260.     while (theSection) {
  261.         ReadASection(theSection);
  262.         theSection = (*theSection)->fNextSection;
  263.     }
  264. }
  265.  
  266. /**-----------------------------------------------------------------------
  267. Name:         ReadSectionRecords
  268. Purpose:        Read in all the 'sect' resources and form list
  269.                 of sections in the document.    This is called from the
  270.                 main read document routine.
  271. -----------------------------------------------------------------------**/
  272. #if !defined(powerc) && !defined(__powerc)
  273. #pragma segment Editions
  274. #endif
  275.  
  276. pascal void ReadSectionRecords(DPtr aDoc)
  277. {
  278.     short         theID;
  279.     SectHandle    aSectHandle;
  280.     OSErr         err;
  281.     short         theCount;
  282.  
  283.     /*read in all the 'sect' resources for our document's sections*/
  284.  
  285.     if (aDoc->kind != kDocumentWindow)
  286.         return;
  287.         
  288.     theCount = aDoc->u.reg.numSections;
  289.     if (theCount == 0)
  290.         return;
  291.  
  292.     aDoc->u.reg.numSections = 0;
  293.     for (theID = 1; theID <= theCount; theID++) {
  294.         aSectHandle = (SectHandle)Get1Resource('SECT', theID);
  295.         err = HandToHand((Handle *)&aSectHandle);
  296.  
  297.         /*now add it to the list*/
  298.  
  299.         if (aSectHandle)
  300.             AddSection(aSectHandle, aDoc);
  301.  
  302.         /*here we should recalculate the region for the bounds*/
  303.  
  304.         (*aSectHandle)->fBorderRgn = NewRgn();
  305.  
  306.         (*aSectHandle)->fDocument  = aDoc;
  307.     }
  308. }
  309.  
  310. /**-----------------------------------------------------------------------
  311.         Name:             SaveASection
  312.         Purpose:        Write out the 'sect', rAliasType and rSectionType resources
  313.                                 to file.    Called when the document is saved.
  314.     -----------------------------------------------------------------------**/
  315.  
  316. #if !defined(powerc) && !defined(__powerc)
  317. #pragma segment Editions
  318. #endif
  319.  
  320. pascal void SaveASection(SectHandle aSection, short count)
  321. {
  322.     SectionHandle  EMSection;
  323.     OSErr          err;
  324.     Handle         tempHandle;
  325.  
  326.     HLock((Handle)aSection);
  327.  
  328.     /*save this section as its component rAliasType and rSectionType resource*/
  329.     /*also save as our own section record as a 'sect' resource*/
  330.  
  331.     EMSection  = (*aSection)->fSectHandle;
  332.     tempHandle = (Handle)EMSection;
  333.     err        = HandToHand(&tempHandle);
  334.  
  335.     HLock((Handle)EMSection);
  336.     AddResource(tempHandle, rSectionType, (*EMSection)->sectionID, (StringPtr) "\p");
  337.     err = ResError();
  338.     if (err) {
  339.         ShowError((StringPtr) "\pAddResource- rSectionType", err);
  340.         return;
  341.     }
  342.  
  343.     /*now add the alias resource*/
  344.     tempHandle = (Handle)(*EMSection)->alias;
  345.     err = HandToHand(&tempHandle);
  346.     AddResource(tempHandle, rAliasType, (*EMSection)->sectionID, (StringPtr) "\p");
  347.     if (err) {
  348.         ShowError((StringPtr) "\pAddResource- rAliasType", err);
  349.         return;
  350.     }
  351.  
  352.     /*now add our own resource- for now all the record, although we only need a few fields*/
  353.     tempHandle = (Handle)aSection;
  354.     err  = HandToHand(&tempHandle);
  355.     AddResource(tempHandle, 'SECT', count, (StringPtr) "\p");
  356.     if (err) {
  357.         ShowError((StringPtr) "\pAddResource- SECT", err);
  358.         return;
  359.     }
  360.  
  361.     HUnlock((Handle)aSection);
  362.     HUnlock((Handle)EMSection);
  363. }
  364.  
  365.  /**-----------------------------------------------------------------------
  366.         Name:         SaveSections
  367.         Purpose:        Called to go down to the section list and call SaveASection
  368.                         for each one.
  369.     -----------------------------------------------------------------------**/
  370.  
  371. #if !defined(powerc) && !defined(__powerc)
  372. #pragma segment Editions
  373. #endif
  374.  
  375. pascal void SaveSections(DPtr aDocument)
  376. {
  377.     OSErr          err;
  378.     SectHandle     currSection;
  379.     short          count;
  380.  
  381.     if (aDocument->kind != kDocumentWindow)
  382.         return;
  383.  
  384.     /*go down the list and save each of the sections*/
  385.     /*the resource file is already open for writing*/
  386.  
  387.     count = 1;
  388.     err = ResError();
  389.     if (err) {
  390.         ShowError((StringPtr) "\pHOpenResFile", err);
  391.         return;
  392.     }
  393.  
  394.     /*now go down the list*/
  395.     currSection = aDocument->u.reg.firstSection;
  396.     while (currSection) {
  397.         SaveASection(currSection, count);
  398.         currSection = (*currSection)->fNextSection;
  399.         count ++;
  400.     }
  401. }
  402.  
  403. /**-----------------------------------------------------------------------
  404.     Name:         AssocAllSections
  405.     Purpose:        Associate all the sections in a document with the document.
  406.                     Called on a SaveAs.
  407. -----------------------------------------------------------------------**/
  408.  
  409. #if !defined(powerc) && !defined(__powerc)
  410. #pragma segment Editions
  411. #endif
  412.  
  413. pascal void AssocAllSections(DPtr theDoc)
  414. {
  415.     SectHandle    aSection;
  416.     SectionHandle EMSection;
  417.     OSErr         err;
  418.  
  419.     if (theDoc->kind != kDocumentWindow)
  420.         return;
  421.  
  422.     /*called by DoSaveAs.    Make sure sections are registered with this document*/
  423.     aSection = theDoc->u.reg.firstSection;
  424.     while (aSection) {
  425.         EMSection = (*aSection)->fSectHandle;
  426.         err = AssociateSection(EMSection, &theDoc->theFSSpec);
  427.         aSection  = (*aSection)->fNextSection;
  428.     }
  429. }
  430.  
  431. /**-----------------------------------------------------------------------
  432.         Name:         KeyOKinSubscriber
  433.         Purpose:        Detects arrow keys.
  434.  -----------------------------------------------------------------------**/
  435. #define kChLeft    28
  436. #define kChRight    29
  437. #define kChUp        30
  438. #define kChDown    31
  439.  
  440. #if !defined(powerc) && !defined(__powerc)
  441. #pragma segment Editions
  442. #endif
  443.  
  444. pascal Boolean KeyOKinSubscriber(char whatKey)
  445. {
  446.     return(     (whatKey==kChUp) 
  447.         ||     (whatKey==kChDown) 
  448.         ||     (whatKey==kChLeft) 
  449.         ||     (whatKey==kChRight));
  450. } /*KeyOKinSubscriber*/
  451.  
  452. /**-----------------------------------------------------------------------
  453.         Name:         ShiftSection
  454.         Purpose:        Moves a section by howMany characters.
  455.  -----------------------------------------------------------------------**/
  456.  
  457. pascal void ShiftSection(SectHandle whichSection, short howMany)
  458. {
  459.     (*whichSection)->fStart += howMany;
  460.     (*whichSection)->fEnd   += howMany;
  461. }  /* ShiftSection */
  462.  
  463. /**-----------------------------------------------------------------------
  464. Name:         DoSectionRecalc
  465. Purpose:        Keeps track of the positions of the sections.
  466. -----------------------------------------------------------------------**/
  467.  
  468. #if !defined(powerc) && !defined(__powerc)
  469. #pragma segment Editions
  470. #endif
  471.  
  472. pascal void DoSectionRecalc(DPtr theDoc, short toAdd)
  473. {
  474.     short        theStartPos;
  475.     short        theEndPos;
  476.     short        oldSectionStart;
  477.     short        oldSectionEnd;
  478.     SectHandle   aSection;
  479.     Boolean      wasChanged;
  480.     GrafPtr      oldPort;
  481.  
  482.     if (theDoc->kind != kDocumentWindow)
  483.         return;
  484.  
  485.     /*
  486.         Work thru all sections -
  487.         1) Those spanning area of modification get modified or zapped
  488.         2) Those after get shifted back or forwards.
  489.  
  490.         Sorry it is so complicated - there's a lot of possibilities
  491.     */
  492.     theStartPos = (*(theDoc->theText))->selStart;
  493.     theEndPos   = (*(theDoc->theText))->selEnd;
  494.  
  495.     aSection = theDoc->u.reg.firstSection;
  496.     while (aSection) {
  497.         wasChanged = true;
  498.  
  499.         oldSectionEnd   = (*aSection)->fEnd;
  500.         oldSectionStart = (*aSection)->fStart;
  501.  
  502.         if (theEndPos < (*aSection)->fStart)
  503.             ShiftSection(aSection, toAdd - (theEndPos-theStartPos));
  504.         else if (theStartPos == (*aSection)->fStart)
  505.             if (theEndPos == (*aSection)->fStart)
  506.                 ShiftSection(aSection, toAdd - (theEndPos-theStartPos));
  507.             else if (theEndPos >= (*aSection)->fEnd) /* section becomes pasted text */
  508.                 (*aSection)->fEnd = (*aSection)->fStart + toAdd;
  509.             else                                                                    /* insert pasted text */
  510.                 (*aSection)->fEnd = (*aSection)->fEnd + toAdd - (theEndPos-theStartPos);
  511.         else if (theStartPos< (*aSection)->fStart)
  512.             (*aSection)->fStart = theStartPos + toAdd; /* move start to end of pasted text */
  513.         else if (theStartPos <= (*aSection)->fEnd)
  514.             if (theEndPos >= (*aSection)->fEnd) /* end of section becomes pasted text */
  515.                 (*aSection)->fEnd = theStartPos + toAdd ;
  516.             else                                                                    /* insert pasted text into section */
  517.                 (*aSection)->fEnd = (*aSection)->fEnd + toAdd - (theEndPos-theStartPos);
  518.         else
  519.             wasChanged = false;
  520.  
  521.         if (wasChanged) {
  522.             (*aSection)->fCount = (*aSection)->fEnd - (*aSection)->fStart;
  523.  
  524.             if (theDoc->u.reg.showBorders) { /* Force an update of the borders - later*/
  525.                 GetPort(&oldPort);
  526.                 SetPort(theDoc->theWindow);
  527.  
  528.                 SetSelectionRgn(theDoc->theText,
  529.                                      oldSectionStart,
  530.                                      oldSectionEnd,
  531.                                      &(*aSection)->fBorderRgn);
  532.                 InvalRgn((*aSection)->fBorderRgn);
  533.  
  534.                 SetPort(oldPort);
  535.             }
  536.         }
  537.  
  538.         aSection = (*aSection)->fNextSection;
  539.     }
  540. }  /* DoSectionRecalc */
  541.  
  542. /**-----------------------------------------------------------------------
  543. Name:         ReadAnEdition
  544. Purpose:        Read the latest version of an edition from disk.
  545. -----------------------------------------------------------------------**/
  546.  
  547. #if !defined(powerc) && !defined(__powerc)
  548. #pragma segment Editions
  549. #endif
  550.  
  551. pascal void ReadAnEdition(SectionHandle mySectHdl)
  552. {
  553.     SectHandle    aSectHandle;
  554.     EditionRefNum theRefNum;
  555.     OSErr         err;
  556.     Ptr           p;
  557.     Size          cutSize;
  558.  
  559.     p = nil;
  560.  
  561.     if (!mySectHdl) {
  562.         ShowError((StringPtr) "\pmySectHdl is NIL", 0);
  563.         return;
  564.     }
  565.  
  566.     aSectHandle = (SectHandle)GetERefCon(mySectHdl);
  567.     if (!aSectHandle) {
  568.         ShowError((StringPtr) "\paSectHandle is NIL", 0);
  569.         return;
  570.     }
  571.  
  572.     GetDateTime(&(*mySectHdl)->mdDate);
  573.  
  574.     /*read a subscriber in from disk.    Usually in response to a sectionread event*/
  575.  
  576.     if (err = OpenEdition(mySectHdl, &theRefNum)) {
  577.         ShowError((StringPtr) "\pOpenEdition in ReadAnEdition", err);
  578.         return;
  579.     }
  580.  
  581.     if (err = EditionHasFormat(theRefNum, 'TEXT', &cutSize)) {
  582.         ShowError((StringPtr) "\pEditionHasFormat in ReadAnEdition", err);
  583.         return;
  584.     }
  585.  
  586.     if (err = SetEditionFormatMark(theRefNum, 'TEXT', 0)) {
  587.         ShowError((StringPtr) "\pSetEditionFormatMark in ReadAnEdition", err);
  588.         return;
  589.     }
  590.  
  591.     /*set up a buffer for the text we're going to read in*/
  592.     p = NewPtr(cutSize);
  593.     if (!p) {
  594.         ShowError((StringPtr) "\pInsufficient memory to read edition", MemError());
  595.         return;
  596.     }
  597.  
  598.     if (err = ReadEdition(theRefNum, 'TEXT', p, &cutSize)) {
  599.         ShowError((StringPtr) "\pReadEdition", err);
  600.         return;
  601.     }
  602.  
  603.     if (err = CloseEdition(theRefNum, true)) {
  604.         ShowError((StringPtr) "\pCloseEdition", err);
  605.         return;
  606.     }
  607.  
  608.     /*
  609.         Ensure this section has a region and invalidate the old region
  610.     */
  611.  
  612.     if ((*aSectHandle)->fBorderRgn == nil)
  613.         (*aSectHandle)->fBorderRgn = NewRgn();
  614.  
  615.     SetSelectionRgn(((*aSectHandle)->fDocument)->theText,
  616.                          (*aSectHandle)->fStart,
  617.                          (*aSectHandle)->fEnd,
  618.                          &(*aSectHandle)->fBorderRgn);
  619.  
  620.     InvalRgn((*aSectHandle)->fBorderRgn);
  621.  
  622.     /*now insert the text in the right place by setting the selection range*/
  623.     /*we want this to act like paste, but without putting the contents on the clipboard*/
  624.     /*so we have to delete the current selection range and then insert our new text*/
  625.  
  626.     /*
  627.         Also fixup section info. for other moved sections
  628.     */
  629.  
  630.     TESetSelect((*aSectHandle)->fStart, (*aSectHandle)->fEnd, ((*aSectHandle)->fDocument)->theText);
  631.     DoSectionRecalc((*aSectHandle)->fDocument, cutSize);
  632.  
  633.     TEDelete(((*aSectHandle)->fDocument)->theText);
  634.     TEInsert(p, cutSize, ((*aSectHandle)->fDocument)->theText);
  635.  
  636.     /*
  637.         Now a little fix up - if the section was previously empty the
  638.         DoSectionRecalc will have put the text in before the section.
  639.         It's like that so you can type in before a subscriber in an
  640.         otherwise empty document. So now pull the start of this section
  641.         back to include the text we just added.
  642.     */
  643.  
  644.     (*aSectHandle)->fStart = (*aSectHandle)->fEnd - cutSize;
  645.  
  646.     /*
  647.         Force redraw of this region
  648.     */
  649.  
  650.     SetSelectionRgn(((*aSectHandle)->fDocument)->theText, 
  651.                          (*aSectHandle)->fStart,
  652.                          (*aSectHandle)->fEnd,
  653.                          &(*aSectHandle)->fBorderRgn);
  654.  
  655.     InvalRgn((*aSectHandle)->fBorderRgn);
  656.  
  657.     DisposPtr(p);
  658. }
  659.  
  660. /**-----------------------------------------------------------------------
  661. Name:         WriteAnEdition
  662. Purpose:        Write out the latest version of an Edition.
  663.                 Called on a Save and on selecting WriteEdition now from
  664.                 the Publisher Options dialog.
  665. -----------------------------------------------------------------------**/
  666.  
  667. #if !defined(powerc) && !defined(__powerc)
  668. #pragma segment Editions
  669. #endif
  670.  
  671. pascal void WriteAnEdition(SectionHandle mySectHdl)
  672. {
  673.     OSErr           err;
  674.     SectHandle      aSectHandle;
  675.     EditionRefNum   theRefNum;
  676.     Handle          aHandle;
  677.     FSSpecPtr       theFSSpecPtr;
  678.  
  679.     aSectHandle = (SectHandle)GetERefCon(mySectHdl);
  680.     /*alter the modification date for the section*/
  681.     GetDateTime(&(*mySectHdl)->mdDate);
  682.     /*write out the edition.  Assume that it is a publisher for now*/
  683.     /*subscribers will be opened for writing with OpenEdition*/
  684.  
  685.     if (((*aSectHandle)->fDocument)->u.reg.everSaved == false)
  686.         theFSSpecPtr = nil;
  687.     else
  688.         theFSSpecPtr = &((*aSectHandle)->fDocument)->theFSSpec;
  689.  
  690.     if (err = OpenNewEdition(mySectHdl, MPAppSig, theFSSpecPtr, &theRefNum)) {
  691.         ShowError((StringPtr) "\pOpenNewEdition", err);
  692.         return;
  693.     }
  694.  
  695.     if (err = SetEditionFormatMark(theRefNum, 'TEXT', 0)) {
  696.         ShowError((StringPtr) "\pSetEditionFormatMark", err);
  697.         return;
  698.     }
  699.  
  700.     /*now get a handle to the text to be written out*/
  701.     /*use the same start and end positions for now, increasing and decreasing*/
  702.     /*the selection will be implemented later*/
  703.  
  704.     aHandle = GetHandleToText(((*aSectHandle)->fDocument)->theText,
  705.                                       (*aSectHandle)->fStart,
  706.                                       (*aSectHandle)->fEnd);
  707.     HLock(aHandle);
  708.  
  709.     /*make sure the count is up to date*/
  710.     (*aSectHandle)->fCount = (*aSectHandle)->fEnd - (*aSectHandle)->fStart;
  711.  
  712.     if (err = WriteEdition(theRefNum, 'TEXT', *aHandle, (*aSectHandle)->fCount)) {
  713.         ShowError((StringPtr) "\pWriteEdition", err);
  714.         return;
  715.     }
  716.     HUnlock(aHandle);
  717.  
  718.     /*remember to save the section and alias records as resources later*/
  719.  
  720.     /*now close the edition*/
  721.  
  722.     if (err = CloseEdition(theRefNum, true)) {
  723.         ShowError((StringPtr) "\pCloseEdition", err);
  724.         return;
  725.     }
  726.  
  727.     /*
  728.         Clean Up
  729.     */
  730.  
  731.     DisposHandle(aHandle);
  732. }     /*WriteAnEdition*/
  733.  
  734. /**-----------------------------------------------------------------------
  735.     Name:         WriteAllEditions
  736.     Purpose:        Go down the list and call WriteAnEdition
  737. -----------------------------------------------------------------------**/
  738.  
  739. #if !defined(powerc) && !defined(__powerc)
  740. #pragma segment Editions
  741. #endif
  742.  
  743. pascal void WriteAllEditions(DPtr aDocument)
  744. {
  745.     SectHandle      aSection;
  746.     SectionHandle   EMSection;
  747.  
  748.     if (aDocument->kind != kDocumentWindow)
  749.         return;
  750.         
  751.     /*called on a Save, to write out all editions*/
  752.     aSection = aDocument->u.reg.firstSection;
  753.  
  754.     while (aSection) {
  755.         EMSection = (*aSection)->fSectHandle;
  756.         if ((*EMSection)->kind == stPublisher)
  757.             WriteAnEdition(EMSection);
  758.         aSection = (*aSection)->fNextSection;
  759.     }
  760. }
  761.  
  762. /**-----------------------------------------------------------------------
  763. Name:         DeRegisterAllSections
  764. Purpose:        Called on cancel Publisher/Subscriber and on a close.
  765. -----------------------------------------------------------------------**/
  766.  
  767. #if !defined(powerc) && !defined(__powerc)
  768. #pragma segment Editions
  769. #endif
  770.  
  771. pascal void DeRegisterAllSections(DPtr aDoc)
  772.   {
  773.         SectHandle      aSection;
  774.         SectionHandle   EMSection;
  775.         OSErr           err;
  776.  
  777.         aSection = aDoc->u.reg.firstSection;
  778.         while (aSection)
  779.             {
  780.                 EMSection = (*aSection)->fSectHandle;
  781.                 err = UnRegisterSection(EMSection);
  782.                 aSection = (*aSection)->fNextSection;
  783.             }
  784.     }
  785.  
  786. /**-----------------------------------------------------------------------
  787. Name:         GetHandleToText
  788. Purpose:        Get a handle to the current text selection.
  789.                 Used to provide a preview on Create Publisher...
  790. -----------------------------------------------------------------------**/
  791.  
  792. #if !defined(powerc) && !defined(__powerc)
  793. #pragma segment Editions
  794. #endif
  795.  
  796. pascal Handle GetHandleToText(TEHandle aTEHandle, short theStart, short theEnd)
  797. {
  798.     OSErr     err;
  799.     Handle    myHandle;
  800.     Ptr       p;
  801.  
  802.     HLock((*aTEHandle)->hText);
  803.     p  = *((*aTEHandle)->hText);
  804.     p  += theStart;
  805.     err = PtrToHand(p, &myHandle, (theEnd - theStart));
  806.     HUnlock((*aTEHandle)->hText);
  807.     return(myHandle);
  808. } /* GetHandleToText */
  809.  
  810. /**-----------------------------------------------------------------------
  811.         Name:         FindLine
  812.         Purpose:        Find the line a character is in.
  813.                         Used to find to calculate the region to use for the Publisher/
  814.                         Subscriber borders.
  815.     -----------------------------------------------------------------------**/
  816.  
  817. #if !defined(powerc) && !defined(__powerc)
  818. #pragma segment Editions
  819. #endif
  820.  
  821. pascal short FindLine(short thePos,TEHandle theTEHandle)
  822. {
  823.     short    index;
  824.     short    theFirstPos;
  825.     short    theNextPos;
  826.  
  827.     index = 0;
  828.  
  829.     do {
  830.         theFirstPos = (*theTEHandle)->lineStarts[index];
  831.         theNextPos  = (*theTEHandle)->lineStarts[index + 1];
  832.         index++;
  833.     } while (! (((thePos >= theFirstPos) && (thePos < theNextPos)) ||
  834.                     (index > (*theTEHandle)->nLines)));
  835.  
  836.     return(index);
  837. }
  838.  
  839. /**-----------------------------------------------------------------------
  840.         Name:         DrawSelectionRgn
  841.         Purpose:        Given a text handle and a start and end position this routine
  842.                         will draw a section border around the selected text.
  843.                         Must allow for the case when the section has no text in it-
  844.                         but we still want to show it as a published section
  845.  -----------------------------------------------------------------------**/
  846.  
  847. pascal void DrawSelectionRegion(TEHandle theTEHandle, short posStart, short posEnd)
  848. {
  849.     RgnHandle  theSelRgn;
  850.     
  851.     theSelRgn = NewRgn();
  852.     
  853.     SetSelectionRgn(theTEHandle, posStart, posEnd,&theSelRgn);
  854.     FrameRgn(theSelRgn);
  855.     
  856.     DisposeRgn(theSelRgn);
  857. } /* DrawSelectionRegion */
  858.  
  859. /**-----------------------------------------------------------------------
  860.         Name:         SetSelectionRgn
  861.         Purpose:        Given a text handle and a start and end position this routine
  862.                         will return the region which is necessary to draw a section
  863.                         border around the selected text.
  864.                         Must allow for the case when the section has no text in it-
  865.                         but we still want to show it as a published section
  866.  -----------------------------------------------------------------------**/
  867.  
  868. #if !defined(powerc) && !defined(__powerc)
  869. #pragma segment Editions
  870. #endif
  871.  
  872. pascal void SetSelectionRgn(TEHandle theTEHandle, short posStart, short posEnd, RgnHandle *theSelRgn)
  873. {
  874.     Point           theStart;
  875.     Point           theEnd;
  876.     short           startLine;
  877.     short           endLine;
  878.     Rect            theRect;
  879.     short           theLeft;
  880.     short           theRight;
  881.     short           theBottom;
  882.     short           theTop;
  883.     short           slineHeight;
  884.     short           elineHeight;
  885.     short           fontAscent;
  886.     TextStyle       theTStyle;
  887.  
  888.     /*first of all find out if the text is on the same line*/
  889.     startLine = FindLine(posStart, theTEHandle);
  890.     endLine   = FindLine(posEnd, theTEHandle);
  891.  
  892.     theStart = TEGetPoint(posStart, theTEHandle);
  893.     theEnd   = TEGetPoint(posEnd, theTEHandle);
  894.  
  895. /*
  896. Get the line height info
  897. */
  898.     TEGetStyle(posStart, &theTStyle, &slineHeight, &fontAscent, theTEHandle);
  899.     TEGetStyle(posEnd,   &theTStyle, &elineHeight, &fontAscent, theTEHandle);
  900.  
  901.     if (startLine == endLine) {
  902.         /*use the start and end points to form the rectangle and draw this into the region*/
  903.         theStart.v -= slineHeight;
  904.         Pt2Rect(theStart, theEnd, &theRect);
  905.         InsetRect(&theRect, - 1, - 1);
  906.         RectRgn(*theSelRgn, &theRect);
  907.     } else {
  908.         theLeft  = (*theTEHandle)->destRect.left;
  909.         theRight = (*theTEHandle)->destRect.right;
  910.         theTop   = theStart.v - slineHeight;
  911.         theBottom  = theEnd.v;
  912.         OpenRgn();
  913.         MoveTo(theStart.h, theStart.v - slineHeight);
  914.         LineTo(theRight, theStart.v - slineHeight);
  915.         LineTo(theRight, theEnd.v - elineHeight);
  916.         LineTo(theEnd.h, theEnd.v - elineHeight);
  917.         LineTo(theEnd.h, theEnd.v);
  918.         LineTo(theLeft, theEnd.v);
  919.         LineTo(theLeft, theStart.v);
  920.         LineTo(theStart.h, theStart.v);
  921.         LineTo(theStart.h, theStart.v - slineHeight);
  922.         CloseRgn(*theSelRgn);
  923.     }
  924.  
  925.     InsetRgn(*theSelRgn, - 2, - 2);
  926. }
  927.  
  928. /**-----------------------------------------------------------------------
  929.         Name:         ShowSectionBorders
  930.         Purpose:        Show the borders for all the sections in a document.
  931.                         Show a Publisher border in 50% gray, a subscriber in 75% gray
  932.  -----------------------------------------------------------------------**/
  933.  
  934. #if !defined(powerc) && !defined(__powerc)
  935. #pragma segment Editions
  936. #endif
  937.  
  938. pascal void ShowSectionBorders(DPtr aDoc)
  939. {
  940.     SectHandle aSection;
  941.  
  942.     if (aDoc->kind != kDocumentWindow)
  943.         return;
  944.         
  945.     PenNormal();
  946.     PenSize(3, 3);
  947.     PenPat(&qd.gray);
  948.     aSection = aDoc->u.reg.firstSection;
  949.     while (aSection) {
  950.         if ((*aSection)->fBorderRgn) {
  951.             SetSelectionRgn(((*aSection)->fDocument)->theText,
  952.                                  (*aSection)->fStart,
  953.                                  (*aSection)->fEnd,
  954.                                  &(*aSection)->fBorderRgn);
  955.  
  956.             if ((*(*aSection)->fSectHandle)->kind == stPublisher)
  957.                 PenPat(&qd.gray);
  958.             else
  959.                 PenPat(&qd.dkGray);
  960.  
  961.             FrameRgn((*aSection)->fBorderRgn);
  962.             PenNormal();
  963.         }
  964.         aSection = (*aSection)->fNextSection;
  965.     }
  966.     PenNormal();
  967. }
  968.  
  969. /**-----------------------------------------------------------------------
  970.         Name:         RecalcBorders
  971.         Purpose:        Recalculate all the borders for the sections in a document.
  972.  -----------------------------------------------------------------------**/
  973.  
  974. #if !defined(powerc) && !defined(__powerc)
  975. #pragma segment Editions
  976. #endif
  977.  
  978. pascal void RecalcBorders(DPtr aDoc, Boolean invalidate)
  979. {
  980.     SectHandle  aSection;
  981.  
  982.     if (aDoc->kind != kDocumentWindow)
  983.         return;
  984.         
  985.     /*go down the section list and recalculate all the borders*/
  986.     aSection = aDoc->u.reg.firstSection;
  987.     while (aSection) {
  988.         if ((*aSection)->fBorderRgn) {
  989.             if (invalidate)
  990.                 InvalRgn((*aSection)->fBorderRgn);
  991.  
  992.             SetSelectionRgn(((*aSection)->fDocument)->theText,
  993.                                  (*aSection)->fStart,
  994.                                  (*aSection)->fEnd,
  995.                                  &(*aSection)->fBorderRgn);
  996.  
  997.             if (invalidate)
  998.                 InvalRgn((*aSection)->fBorderRgn);
  999.         }
  1000.         aSection = (*aSection)->fNextSection;
  1001.     }
  1002. }
  1003.  
  1004. /**-----------------------------------------------------------------------
  1005.         Name:         GetSection
  1006.         Purpose:        Given a start and end of a selection- return the section
  1007.                         handle if it is in a Publisher or Subscriber.
  1008.  -----------------------------------------------------------------------**/
  1009.  
  1010. #if !defined(powerc) && !defined(__powerc)
  1011. #pragma segment Editions
  1012. #endif
  1013.  
  1014. pascal SectHandle GetSection(short theStartPos, short theEndPos, DPtr aDoc)
  1015. {
  1016.     SectHandle   foundSection;
  1017.     SectHandle   aSection;
  1018.  
  1019.     /*returns the section handle for the section between theStartPos and theEndPos*/
  1020.  
  1021.     if (aDoc->kind != kDocumentWindow)
  1022.         return nil;
  1023.         
  1024.     foundSection = nil;
  1025.  
  1026.     aSection = aDoc->u.reg.firstSection;
  1027.     while (aSection) {
  1028.         if ((theStartPos >= (*aSection)->fStart) && (theEndPos <= (*aSection)->fEnd))
  1029.             foundSection = aSection;
  1030.         aSection = (*aSection)->fNextSection;
  1031.     }
  1032.  
  1033.     return foundSection;
  1034. }
  1035.  
  1036. /**-----------------------------------------------------------------------
  1037.         Name:         DoTEPasteSectionRecalc
  1038.         Purpose:        Keeps track of the positions of the sections call before a
  1039.                     TEPaste or TEStylPaste.
  1040.  -----------------------------------------------------------------------**/
  1041.  
  1042. pascal void DoTEPasteSectionRecalc(DPtr theDoc)
  1043. {
  1044.     short toAdd;
  1045.  
  1046.     if (theDoc->kind != kDocumentWindow)
  1047.         return;
  1048.         
  1049.     toAdd = TEGetScrapLen();
  1050.     DoSectionRecalc(theDoc, toAdd);
  1051. }  /* DoTEPasteSectionRecalc */
  1052.  
  1053. /**-----------------------------------------------------------------------
  1054.         Name:         DoTEDeleteSectionRecalc
  1055.         Purpose:        Keeps track of the positions of the sections call before a
  1056.                     TEDelete.
  1057.  -----------------------------------------------------------------------**/
  1058.  
  1059. pascal void DoTEDeleteSectionRecalc(DPtr theDoc)
  1060. {
  1061.     if (theDoc->kind != kDocumentWindow)
  1062.         return;
  1063.         
  1064.     DoSectionRecalc(theDoc, 0);
  1065. }  /* DoTEDeleteSectionRecalc */
  1066.  
  1067. /**-----------------------------------------------------------------------
  1068.         Name:         DoTECutSectionRecalc
  1069.         Purpose:        Keeps track of the positions of the sections call before a
  1070.                     TECut.
  1071.  -----------------------------------------------------------------------**/
  1072.  
  1073. pascal void DoTECutSectionRecalc(DPtr theDoc)
  1074. {
  1075.     if (theDoc->kind != kDocumentWindow)
  1076.         return;
  1077.         
  1078.     DoSectionRecalc(theDoc, 0);
  1079. }  /* DoTEDeleteSectionRecalc */
  1080.  
  1081. /**-----------------------------------------------------------------------
  1082.         Name:         DoTEKeySectionRecalc
  1083.         Purpose:        Keeps track of the positions of the sections call before a
  1084.                     TECut.
  1085.  -----------------------------------------------------------------------**/
  1086.  
  1087. pascal void DoTEKeySectionRecalc(DPtr theDoc,char theChar)
  1088. {
  1089.     short     toAdd;
  1090.     short     oldStart;
  1091.  
  1092.     if (theDoc->kind != kDocumentWindow)
  1093.         return;
  1094.         
  1095.     if (!KeyOKinSubscriber(theChar)) /* is it a cursor motion key? - yes = ignore */ {
  1096.         if (theChar==8)
  1097.             if ((*(theDoc->theText))->selStart<(*(theDoc->theText))->selEnd)
  1098.                 toAdd = 0;
  1099.             else {
  1100.                 toAdd = -1;
  1101.                 oldStart = (*(theDoc->theText))->selStart;
  1102.  
  1103.                 (*(theDoc->theText))->selStart = GreaterOf(oldStart-1,0);
  1104.                 DoSectionRecalc(theDoc, 0);
  1105.                 (*(theDoc->theText))->selStart = oldStart;
  1106.             }
  1107.         else
  1108.             toAdd = 1;
  1109.  
  1110.         if (toAdd!=-1)
  1111.             DoSectionRecalc(theDoc, toAdd);
  1112.     }
  1113. }  /* DoTEKeySectionRecalc */
  1114.  
  1115. /**-----------------------------------------------------------------------
  1116.         Name:         GetEditionContainer
  1117.         Purpose:        Gets the Edition Container to put the edition into.
  1118.                         The main user interface stuff.
  1119.                         Puts up the new publisher dialog.
  1120.                         Should check kAEInteractWithUser etc.
  1121.  -----------------------------------------------------------------------**/
  1122.  
  1123. #if !defined(powerc) && !defined(__powerc)
  1124. #pragma segment Main
  1125. #endif
  1126.  
  1127. pascal OSErr GetEditionContainer(DPtr theDoc, FSSpec *theFSSpec)
  1128. {
  1129.     OSErr             err;
  1130.     NewPublisherReply myReply;
  1131.     short             theStart;
  1132.     short             theEnd;
  1133.     Handle            myHandle;
  1134.     TEHandle          myText;
  1135.  
  1136.     if (theDoc->kind != kDocumentWindow)
  1137.         return noErr;
  1138.         
  1139.     err = noErr;
  1140.  
  1141.     /*get default editionContainer to use, using last volume and folder*/
  1142.  
  1143.     myReply.container.thePart = kPartsNotUsed;
  1144.  
  1145.     err = GetLastEditionContainerUsed(&myReply.container);
  1146.  
  1147.     if (err==fnfErr)
  1148.         err = noErr;
  1149.  
  1150.     myText = theDoc->theText;
  1151.  
  1152.     theStart = (*myText)->selStart;
  1153.     theEnd   = (*myText)->selEnd;
  1154.  
  1155.     if (err==noErr) {
  1156.         /*
  1157.             Create a handle containing the text to be published for previewing -
  1158.             need to ask the user where to put the data
  1159.         */
  1160.         myHandle = GetHandleToText(myText, theStart, theEnd);
  1161.  
  1162.         myReply.usePart       = false;
  1163.         myReply.preview       = myHandle;
  1164.         myReply.previewFormat = 'TEXT';
  1165.         myReply.container.theFile.name[0] = 0; /* Want a proper prompted name here */
  1166.         HLock(myHandle);
  1167.  
  1168.         /* Should take suggested name and avoid dialog if no user interaction */
  1169.  
  1170.         err = AEInteractWithUser(kAEDefaultTimeout, nil, nil);
  1171.  
  1172.         err = NewPublisherDialog(&myReply);
  1173.         HUnlock(myHandle);
  1174.         DisposHandle(myHandle);
  1175.     }
  1176.  
  1177.     /*IF user cancelled, THEN exit from this routine*/
  1178.  
  1179.     if (err==noErr)
  1180.         if (myReply.canceled)
  1181.             err = userCanceledErr; /* User cancelled marker - replace later */
  1182.  
  1183.     if (err==noErr)
  1184.         if (myReply.replacing)
  1185.             err = FSpDelete(&myReply.container.theFile);
  1186.  
  1187.     if (err == noErr)
  1188.         *theFSSpec = myReply.container.theFile;
  1189.  
  1190.     return(err);
  1191. } /*GetEditionContainer*/
  1192.  
  1193.  
  1194. /**-----------------------------------------------------------------------
  1195.         Name:             PublishText
  1196.         Purpose:        Publishes the current selection of theDoc.
  1197.                                 The main user interface stuff.
  1198.                                 Puts up the new publisher dialog - if theFSSpec=NIL
  1199.                                 Writes the new edition out to disk.
  1200.  -----------------------------------------------------------------------**/
  1201.  
  1202. #if !defined(powerc) && !defined(__powerc)
  1203. #pragma segment Main
  1204. #endif
  1205.  
  1206. pascal OSErr PublishText(DPtr theDoc, FSSpecPtr theFSSpec)
  1207. {
  1208.     NewPublisherReply myReply;
  1209.     SectionHandle        mySectHdl;
  1210.     OSErr                 err;
  1211.     long               mysectionID;
  1212.     FSSpecPtr             pubFSSpec;
  1213.     short                 theStart;
  1214.     short                 theEnd;
  1215.     RgnHandle             theRgnHandle;
  1216.  
  1217.     if (theDoc->kind != kDocumentWindow)
  1218.         return noErr;
  1219.         
  1220.     mysectionID            = theDoc->u.reg.lastID + 1;
  1221.     theDoc->u.reg.lastID = mysectionID;
  1222.  
  1223.     /*get default editionContainer to use, using last volume and folder*/
  1224.  
  1225.     myReply.container.thePart = kPartsNotUsed;
  1226.  
  1227.     err = GetLastEditionContainerUsed(&myReply.container);
  1228.  
  1229.     if (err==fnfErr)
  1230.         err = noErr;
  1231.  
  1232.     theStart = (*theDoc->theText)->selStart;
  1233.     theEnd   = (*theDoc->theText)->selEnd;
  1234.  
  1235.     /*don't want to publish an empty section*/
  1236.  
  1237.     if (theEnd - theStart == 0)
  1238.         err = userCanceledErr;
  1239.  
  1240.     myReply.container.theFile = *theFSSpec;
  1241.  
  1242.     /*now publish this section*/
  1243.  
  1244.     if (err == noErr)
  1245.         err = CreateEditionContainerFile(&myReply.container.theFile, MPAppSig, 0);
  1246.  
  1247.     /*check IF the file has been saved, IF not set pubCFS to NIL*/
  1248.  
  1249.     if (theDoc->u.reg.everSaved == false)
  1250.         pubFSSpec = nil;
  1251.     else
  1252.         pubFSSpec = &theDoc->theFSSpec;
  1253.  
  1254.     /*get the region to encompass the selection*/
  1255.  
  1256.     theRgnHandle = NewRgn();
  1257.     SetSelectionRgn(theDoc->theText,
  1258.                          (*theDoc->theText)->selStart,
  1259.                                     (*theDoc->theText)->selEnd,
  1260.                                     &theRgnHandle);
  1261.  
  1262.     InvalRgn(theRgnHandle);
  1263.  
  1264.     /*create a publisher section*/
  1265.     if (err==noErr) {
  1266.         err = NewSection(&myReply.container,
  1267.                               pubFSSpec,
  1268.                               stPublisher,
  1269.                               mysectionID,
  1270.                               pumOnSave,
  1271.                               &mySectHdl);
  1272.  
  1273.         /*now add this section to our document list*/
  1274.  
  1275.         if (err == noErr)
  1276.             CreateSection(mySectHdl, mysectionID, theStart, theEnd, theDoc, theRgnHandle);
  1277.     }
  1278.  
  1279.     /*now write out the edition to file*/
  1280.  
  1281.     if (err==noErr)
  1282.         WriteAnEdition(mySectHdl);
  1283.  
  1284.     return(err);
  1285. } /*PublishText*/
  1286.  
  1287. /**-----------------------------------------------------------------------
  1288.         Name:         DoSubscribe
  1289.         Purpose:        Subscribe to a published section. Puts up the subscriber
  1290.                         dialog, creates and adds the new section.
  1291.  -----------------------------------------------------------------------**/
  1292.  
  1293. #if !defined(powerc) && !defined(__powerc)
  1294. #pragma segment Main
  1295. #endif
  1296.  
  1297. pascal void DoSubscribe(DPtr theDoc)
  1298. {
  1299.     NewSubscriberReply myReply;
  1300.     SectionHandle      mySectHdl;
  1301.     long               mysectionID;
  1302.     FSSpecPtr          subFSSpec; /*the fsspec for the subscriber file*/
  1303.     OSErr              err;
  1304.     short              theStart;
  1305.     short              theEnd;
  1306.  
  1307.     if (theDoc->kind != kDocumentWindow)
  1308.         return;
  1309.         
  1310.     mysectionID = theDoc->u.reg.lastID + 1;
  1311.     theDoc->u.reg.lastID = mysectionID;
  1312.     err = noErr;
  1313.  
  1314.     /*get default editionContainer to use, using last volume and folder*/
  1315.     /*  myreply.container.thePart := kPartNumberUnknown;*/
  1316.     myReply.formatsMask = kTEXTformatMask;
  1317.  
  1318.     err = GetLastEditionContainerUsed(&myReply.container);
  1319.     if (err && (err !=fnfErr)) {
  1320.         ShowError((StringPtr) "\pGetLastEditionContainerUsed", err);
  1321.         return;
  1322.     }
  1323.  
  1324.     /*put up the subscriber dialog*/
  1325.     err = NewSubscriberDialog(&myReply);
  1326.     if (err && (err !=fnfErr)) {
  1327.         ShowError((StringPtr) "\pNewSubscriberDialog", err);
  1328.         return;
  1329.     }
  1330.  
  1331.     if (myReply.canceled)
  1332.         return;
  1333.  
  1334.     /*check IF the file has been saved, IF not set pubCFS to NIL*/
  1335.     if (theDoc->u.reg.everSaved == false)
  1336.         subFSSpec = nil;
  1337.     else
  1338.         subFSSpec = &theDoc->theFSSpec;
  1339.  
  1340.     /*create a publisher section*/
  1341.     err = NewSection(&myReply.container,
  1342.                           subFSSpec,
  1343.                           stSubscriber,
  1344.                           mysectionID,
  1345.                           sumAutomatic,
  1346.                           &mySectHdl);
  1347.  
  1348.     if (err) {
  1349.         ShowError((StringPtr) "\pNewSection", err);
  1350.         return;
  1351.     }
  1352.  
  1353.     theStart = (*theDoc->theText)->selStart;
  1354.     theEnd   = (*theDoc->theText)->selEnd;
  1355.  
  1356.     /*now add this section to our document list*/
  1357.  
  1358.     CreateSection(mySectHdl, mysectionID, theStart, theEnd, theDoc, nil);
  1359.  
  1360.     /*read the subscriber in from disk*/
  1361.  
  1362.     ReadAnEdition(mySectHdl);
  1363.  
  1364. }  /*DoSubscribe*/
  1365.  
  1366. /**-----------------------------------------------------------------------
  1367.         Name:         DoSectionOptions
  1368.         Purpose:        Put up the section option dialogs for a publisher
  1369.                         or subscriber.    Handle all the various options.
  1370.                         Note that 'Find Publisher' doesn't work yet.
  1371.  -----------------------------------------------------------------------**/
  1372.  
  1373. #if !defined(powerc) && !defined(__powerc)
  1374. #pragma segment Main
  1375. #endif
  1376.  
  1377. pascal void DoSectionOptions(DPtr theDoc)
  1378. {
  1379.     OSErr               err;
  1380.     SectionOptionsReply reply;
  1381.     EditionInfoRecord   theInfo;
  1382.     SectHandle          currSection;
  1383.  
  1384.     if (theDoc->kind != kDocumentWindow)
  1385.         return;
  1386.         
  1387.     currSection = GetSection((*theDoc->theText)->selStart,
  1388.                                                      (*theDoc->theText)->selEnd,
  1389.                                                      theDoc);
  1390.  
  1391.     reply.sectionH = (*currSection)->fSectHandle;
  1392.     err = SectionOptionsDialog(&reply);
  1393.     if (!reply.canceled) {
  1394.         /*find out IF there is any action needed*/
  1395.         if (reply.action == 'read')
  1396.         /*read the latest version of a subscriber*/
  1397.             ReadAnEdition((*currSection)->fSectHandle);
  1398.         else if (reply.action == 'writ')
  1399.         /*write out the latest version of a publisher to disk*/
  1400.             WriteAnEdition((*currSection)->fSectHandle);
  1401.         else if (reply.action == 'goto') /*goto a published section*/ {
  1402.             err = GetEditionInfo((*currSection)->fSectHandle, &theInfo);
  1403.  
  1404.             if (err)
  1405.                 ShowError((StringPtr) "\pGetEditionInfo", err);
  1406.  
  1407.             err = GoToPublisherSection(&theInfo.container);
  1408.  
  1409.             if (err)
  1410.                 ShowError((StringPtr) "\pGotoPublisherSection", err);
  1411.         } else if (reply.action == 'cncl') /*cancel a publisher or subscriber*/ {
  1412.             /*unRegister the section and delete from our own list*/
  1413.             /*should have a free PROCEDURE which frees the structures*/
  1414.             /*associated with a section*/
  1415.             err = UnRegisterSection((*currSection)->fSectHandle);
  1416.             DeleteASection(currSection, theDoc);
  1417.  
  1418.             /*IF this is the ONLY publisher writing data to this edition*/
  1419.             /*we should delete the container file as well*/
  1420.         }
  1421.     }
  1422. }
  1423.